/*
 * TODO language 
 * Copyright (c) 2010 TODO Team
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef TODO_TYPES_H
#define TODO_TYPES_H
#include <exception>
#include <vector>
#include <map>
#include <string>
#include "string.h"

#define DEL(x) \
	if ((x).data.type == todo::TODO_STRING && (x).data.val.str) { \
		delete (x).data.val.str; \
		(x).data.val.str = NULL; \
	}

#define IS_NUMERIC(x) ((x) == TODO_INTEGER || (x) == TODO_DOUBLE)

namespace todo
{
typedef enum {
	TODO_NULL = 0,
	TODO_STRING,
	TODO_BOOL,
	TODO_INTEGER,
	TODO_DOUBLE,
	TODO_MAP,
	TODO_VECTOR
} TodoType;

class TodoException : public std::exception {
	const char* message;
public:
	TodoException(const char* message_) : message(message_) { }
	TodoException(const std::string message_) : message(message_.c_str()) { }
	virtual const char* what() const throw() { return message; }
};

struct TodoValue {
	TodoType type;
	union {
		std::string *str;
		int tint;
		double tdouble;
	} val;
	
	TodoValue() : type(TODO_NULL) { }
	~TodoValue() { }
	
	TodoValue& operator/=(TodoValue*) throw (todo::TodoException);
	TodoValue& operator*=(TodoValue*) throw (todo::TodoException);
	TodoValue& operator+=(TodoValue*) throw (todo::TodoException);
	TodoValue& operator-=(TodoValue*) throw (todo::TodoException);
	TodoValue& operator%=(TodoValue*) throw (todo::TodoException);
};

struct todo_func_call {
	std::vector<TodoValue*> args;
	
	todo_func_call() { }
	~todo_func_call();
};

struct TodoFunction {
	TodoType return_type;
	std::map<std::string, TodoType> args;
	unsigned int op_num, last_opcode;
	
	TodoFunction() { }
	~TodoFunction() { }
};

struct TodoScope {
	unsigned int calling_op_num;
	std::map<std::string, TodoValue*> vars;
	std::map<std::string, TodoFunction*> funcs;
	
	TodoScope() { }
	~TodoScope() { }
};

typedef enum {
	TODO_VAR = 0,
	TODO_CONSTANT,
	TODO_UNUSED,
	TODO_RET_VALUE,
	TODO_EXPR_VALUE,
	TODO_JMP
} TodoDataType;

struct TodoData {
	TodoDataType type;
	TodoValue data;
	
	TodoData() { }
	TodoData(TodoDataType type_) : type(type_) { }
	~TodoData() { }
};

} // todo

#endif // TODO_TYPES_H
